package deepbitview

import grails.converters.JSON
import org.codehaus.groovy.grails.web.json.JSONArray
import org.apache.log4j.Logger
import grails.validation.ValidationException

/**
 * access the deep view services and parses the json data
 */
class DeepViewAccessService {

    /**
     * access to the current ticker value
     */
    TickerService tickerService

    /**
     * access to the global statistics
     */
    GlobalStatsService globalStatsService

    Logger logger = Logger.getLogger(getClass())

    static transactional = true

    String source = "http://deepbit.net/api/"

    /**
     * parses the data with the given api key
     * and returns an associated project
     * @param apiKey
     * @return
     */
    def receiveData(String apiKey) {

        //build our complete source url
        String url = "${this.source}${apiKey}"

        //parse our data to a json object
        Map jsonArray = JSON.parse(new InputStreamReader(new URL(url).openStream()))

        def globalStats = globalStatsService.fetchGlobalStats()

        Sample sample = new Sample()

        //our specific data
        sample.reward = Double.parseDouble(jsonArray["confirmed_reward"].toString())
        sample.sampleTime = new Date()
        sample.hashRate = Double.parseDouble(jsonArray["hashrate"].toString())
        sample.exchangeRateUSD = tickerService.fetchLatestUSDExchangeRate()

        //assign the global statistics
        sample.difficulty = globalStats["difficulty"]
        sample.globalBitCoinAmount = globalStats["bitcoins_total"]
        sample.globalyKnownBlocks = globalStats["blocks"]
        sample.globalNetworkSpeed = globalStats["network_speed"]
        sample.nextDifficultyEstimate = globalStats["difficulty_estimate"]

        if (sample.validate() == false) {
            throw new ValidationException("sorry your sample was invalid", sample.errors)
        }
        sample.save(flush: true)

        //associate the workers
        def workers = jsonArray.get("workers")

        //go over all workers and associate the data to the database
        workers.keySet().each {String key ->

            Worker worker = Worker.findByName(key)

            if (worker == null) {
                worker = new Worker()
                worker.name = key
            }

            Map values = workers[key]

            worker.shares = Integer.parseInt(values["shares"].toString())
            worker.stales = Integer.parseInt(values["stales"].toString())

            if (worker.validate() == false) {
                throw new ValidationException("sorry your worker was invalid", worker.errors)
            }
            worker.save(flush: true)

            WorkerInstance workerInstance = new WorkerInstance()
            workerInstance.alive = values["alive"]
            workerInstance.sample = sample
            workerInstance.worker = worker

            if (workerInstance.validate() == false) {
                throw new ValidationException("sorry your worker instance was invalid", workerInstance.errors)
            }
            workerInstance.save(flush: true)
        }

        //synchronization should be done now so let's end this method
    }

    /**
     * receives the data with the default key
     * @return
     */
    def receiveDataWithDefaultKey(){
        String key = ActiviationKeyHandler.getDeepBitActivationKey()
        receiveData(key)
    }

}
